home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_351 / pdc / pdcsrc.lzh / A68k / A68kmain.c < prev    next >
C/C++ Source or Header  |  1990-04-19  |  30KB  |  973 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*            MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*        Copyright (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*                  Main program - November 2, 1989            */
  8. /*                                    */
  9. /*   This program may be copied for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on all copies of the source code.  Copying for any other use   */
  12. /*   without the consent of the author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*              Originally published (in Modula-2) in            */
  17. /*          Dr. Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*       AmigaDOS conversion copyright 1989 by Charlie Gibbs.        */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. char Version[] = "2.6 (November 2, 1989)";
  24.  
  25.  
  26. #include <stdio.h>
  27. #define PRIMARY
  28. #include "A68kdef.h"
  29. #include "A68kglb.h"
  30.  
  31.  
  32. #ifdef MSDOS
  33. /********************************************************************/
  34. /*                                    */
  35. /*     NOTE: the following line, plus any additional references        */
  36. /*     to _iomode, is inserted to make this program work under        */
  37. /*     the MS-DOS version of Lattice C.  It is not necessary        */
  38. /*     for the Amiga version, but does no harm if left in.        */
  39. /*                                    */
  40. /********************************************************************/
  41. int _iomode = 0;    /* File mode - 0x8000 for binary */
  42. #endif
  43.  
  44.  
  45.  
  46. /* Functions */
  47. extern int  LineParts(), Instructions(), ObjDir();
  48. extern int  GetInstModeSize(), GetMultReg(), CountNest();
  49. extern int  ReadSymTab(), GetArgs(), GetAReg(), OpenIncl();
  50. extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue ();
  51. extern char *AddName(), *GetField();
  52. extern struct SymTab *NextSym();
  53. extern struct SymTab **HashIt();
  54.  
  55. int getfilename(), checkswitch(), checkdupfile();
  56.  
  57.  
  58. main (argc,argv) int argc; char *argv[];
  59. {
  60.     char ListFN[MAXFN], EquateFN[MAXFN]; /* File names */
  61.     int  makeequ;            /* Make an equate file. */
  62.     int  keepobj;            /* Keep object file with errors. */
  63.     int  endfile;            /* End-of-file flag */
  64.     long maxheap2;            /* Maximum secondary heap size */
  65.     int  cmderror, dummy;
  66.     long codesize, datasize, bsssize;
  67.     int  *intptr;
  68.     long templong;
  69.     char tempchar[MAXLINE];
  70.     register struct SymTab *sym;
  71.     register int i, j;
  72.     struct SymTab **hashptr, **fsp;
  73.     struct FwdBr *fp1, *fp2, *fp3;
  74.  
  75.     Hash = NULL;    /* Clear all memory pointers - */
  76.     SymStart = NULL;    /*  we haven't allocated anything yet. */
  77.     NameStart = NULL;
  78.     RelStart = NULL;
  79.     Heap2 = NULL;
  80.     SymSort = NULL;
  81.     In.fd = Eq.fd = List.fd = Srec.fd = NULL;    /* No files are open yet. */
  82.     In.Buf = Eq.Buf = List.Buf = Srec.Buf = NULL;
  83.  
  84.     cmderror = FALSE;        /* Clear command-line error flag. */
  85.     InclErrs = FALSE;
  86.     SourceFN[0] = '\0';            /* We don't have source name yet. */
  87.     HeaderFN[0] = EquateFN[0] = '\0';    /* No header or equate files yet */
  88.     makeequ = FALSE;
  89.     ListFN[0] = SrecFN[0] = '\0';    /* Indicate default file names. */
  90.     InclList[0] = '\0';        /* Clear the include directory list. */
  91.     IdntName[0] = '\0';        /* Clear program unit name. */
  92.     LnMax = 60;
  93.     Quiet = 10;            /* Show progress every 10 lines. */
  94.     strcpy (MacSize, "W");    /* Macro call size (\0) */
  95.     XrefList = DumpSym = GotEqur = KeepTabs = keepobj = FALSE;
  96.     SuppList = TRUE;        /* Default to no listing file. */
  97.     HashStats = FALSE;        /* Default to no hashing statistics. */
  98.     HashSize = DEFHASH;        /* Hash table size default */
  99.     maxheap2 = DEFHEAP2;    /* Secondary heap size default */
  100.     DebugStart = 32767; DebugEnd = 0;    /* Disable debug displays. */
  101.  
  102.     for (i = 0; i < 256; i++)
  103.     OpPrec[i] = '\0';    /* Set up the operator precedence table. */
  104.     i = (unsigned int) '('; OpPrec[i] = 1;
  105.     i = (unsigned int) ')'; OpPrec[i] = 2;
  106.     i = (unsigned int) '+'; OpPrec[i] = 3;
  107.     i = (unsigned int) '-'; OpPrec[i] = 3;
  108.     i = (unsigned int) '*'; OpPrec[i] = 4;
  109.     i = (unsigned int) '/'; OpPrec[i] = 4;
  110.     i = (unsigned int) '&'; OpPrec[i] = 5;
  111.     i = (unsigned int) '!'; OpPrec[i] = 5;
  112.     i = (unsigned int) '|'; OpPrec[i] = 5;
  113.     i = (unsigned int) '<'; OpPrec[i] = 6;
  114.     i = (unsigned int) '>'; OpPrec[i] = 6;
  115.  
  116.     for (i = 1; i < argc; i++) {    /* Analyze the command line. */
  117.     if (argv[i][0] != '-') {
  118.         if (SourceFN[0] == '\0')
  119.         strcpy (SourceFN, argv[i]);    /* Source file name */
  120.         else if (SrecFN[0] == '\0')
  121.         strcpy (SrecFN, argv[i]);    /* Object file name */
  122.         else if (ListFN[0] == '\0')
  123.         strcpy (ListFN, argv[i]);    /* Listing file name */
  124.         else {
  125.         fprintf (stderr, "Too many file names.\n");
  126.         cmderror = TRUE;
  127.         }
  128.     } else {
  129.         switch (toupper(argv[i][1])) {
  130.         case 'D':            /* Dump the symbol table. */
  131.         DumpSym = TRUE;
  132.         strcpy (DumpSymList, &argv[i][2]);    /* Selections */
  133.         break;
  134.         case 'E':            /* Equate file name */
  135.         makeequ = TRUE;
  136.         if (getfilename (EquateFN, &argv[i][2], "Equate", FALSE))
  137.             cmderror = keepobj = TRUE;
  138.         break;
  139.         case 'F':            /* Dump the symbol table. */
  140.         FwdProc = TRUE;
  141.         cmderror |= checkswitch (argv[i][2], "forward reference");
  142.         break;
  143.         case 'H':            /* Header file name */
  144.         if (getfilename (HeaderFN, &argv[i][2], "Header", TRUE))
  145.             cmderror = keepobj = TRUE;
  146.         break;
  147.         case 'I':            /* Include directories */
  148.         if (argv[i][2]) {
  149.             if (InclList[0])
  150.             strcat (InclList, ",");    /* Add to previous list */
  151.             strcat (InclList, &argv[i][2]);
  152.         } else {
  153.             fprintf (stderr, "Include directory list is missing.\n");
  154.             cmderror = keepobj = TRUE;
  155.         }
  156.         break;
  157.         case 'K':            /* Keep object code file. */
  158.         keepobj = TRUE;
  159.         cmderror |= checkswitch (argv[i][2], "object file keep");
  160.         break;
  161.         case 'X':            /* Cross-reference listing */
  162.         XrefList = TRUE;    /* Falls through to case 'L': */
  163.         case 'L':            /* Produce a listing file. */
  164.         SuppList = FALSE;
  165.         if (getfilename (ListFN, &argv[i][2], "List", FALSE))
  166.             cmderror = keepobj = TRUE;
  167.         break;
  168.         case 'N':            /* Suppress optimization. */
  169.         NoOpt = TRUE;
  170.         cmderror |= checkswitch (argv[i][2], "optimization suppress");
  171.         break;
  172.         case 'O':            /* Object file name */
  173.         if (getfilename (SrecFN, &argv[i][2], "Object", TRUE))
  174.             cmderror = keepobj = TRUE;
  175.         break;
  176.         case 'P':            /* Page depth */
  177.         if (argv[i][2] == '\0') {
  178.             fprintf (stderr, "Page depth is missing.\n");
  179.             cmderror = keepobj = TRUE;
  180.             break;
  181.         }
  182.         if ((LnMax = CalcValue (&argv[i][2], 0)) < 10) {
  183.             fprintf (stderr, "Page depth is invalid.\n");
  184.             cmderror = TRUE;
  185.         }
  186.         break;
  187.         case 'Q':            /* Quiet console display */
  188.         Quiet = CalcValue (&argv[i][2], 0);
  189.         break;
  190.         case 'S':            /* Motorola S-format */
  191.         SFormat = TRUE;
  192.         cmderror |= checkswitch (argv[i][2], "S-format");
  193.         break;
  194.         case 'T':            /* Keep tabs in listing. */
  195.         KeepTabs = TRUE;
  196.         cmderror |= checkswitch (argv[i][2], "tab");
  197.         break;
  198.         case 'W':            /* Work storage size(s) */
  199.         if (argv[i][2] == '\0') {
  200.             fprintf (stderr, "Work storage size is missing.\n");
  201.             cmderror = keepobj = TRUE;
  202.             break;
  203.         }
  204.         if (argv[i][2] != ',') {
  205.             GetField (argv[i]+2, tempchar);
  206.             HashSize = CalcValue (tempchar, 0);
  207.             if (HashSize >= 16384) {
  208.             fprintf (stderr, "Hash table size is too big.\n");
  209.             cmderror = TRUE;
  210.             }
  211.         }
  212.         for (j = 2; argv[i][j]; j++) {
  213.             if (argv[i][j] == ',') {    /* Find secondary size. */
  214.             maxheap2 = CalcValue (&argv[i][j+1], 0);
  215.             if (maxheap2 < MAXLINE)
  216.                 maxheap2 = MAXLINE;
  217.             maxheap2 &= ~3L;
  218.             break;
  219.             }
  220.         }
  221.         break;
  222.         case 'Y':            /* Display hashing statistics. */
  223.         HashStats = TRUE;
  224.         cmderror |= checkswitch (argv[i][2], "hash statistics");
  225.         break;
  226.         case 'Z':            /* Debug option */
  227.         DebugStart = 0;
  228.         DebugEnd = 32767;
  229.         if (argv[i][2] != ',') {    /* Debug dump starts here. */
  230.             GetField (argv[i]+2, tempchar);
  231.             DebugStart = CalcValue (tempchar, 0);
  232.         }
  233.         for (j = 2; argv[i][j]; j++) {
  234.             if (argv[i][j] == ',') {    /* Debug dump ends here. */
  235.             DebugEnd = CalcValue (&argv[i][j+1], 0);
  236.             if (DebugEnd == 0)
  237.                 DebugEnd = 32767;
  238.             }
  239.         }
  240.         break;
  241.         default:
  242.         fprintf (stderr, "Unrecognized switch: %c\n", argv[i][1]);
  243.         cmderror = TRUE;
  244.         break;
  245.         }
  246.     }
  247.     }
  248.  
  249.     if (makeequ)
  250.     defaultfile (EquateFN, ".equ");    /* Default equate file name */
  251.     if (!SuppList)
  252.     defaultfile (ListFN, ".lst");    /* Default list file name */
  253.     else            /* If there's no listing, don't bother */
  254.     KeepTabs = TRUE;    /*  expanding tabs - it's faster.      */
  255.     if (SFormat)
  256.     defaultfile (SrecFN, ".s");    /* Default S-format file name */
  257.     else
  258.     defaultfile (SrecFN, ".o");    /* Default object file name */
  259.  
  260. /* Check for duplicate file names. */
  261.  
  262.     if (SourceFN[0]) {
  263.     cmderror |= checkdupfile (SourceFN, "Source", EquateFN, "equate");
  264.     cmderror |= checkdupfile (SourceFN, "Source", ListFN, "listing");
  265.     cmderror |= checkdupfile (SourceFN, "Source", SrecFN, "object");
  266.     } else {
  267.     fprintf (stderr, "Source file name is missing.\n");
  268.     cmderror = TRUE;
  269.     }
  270.     if (EquateFN[0]) {
  271.     cmderror |= checkdupfile (EquateFN, "Equate", ListFN, "listing");
  272.     cmderror |= checkdupfile (EquateFN, "Equate", SrecFN, "object");
  273.     }
  274.     if (ListFN[0]) {
  275.     cmderror |= checkdupfile (ListFN, "Listing", SrecFN, "object");
  276.     }
  277.  
  278. /*    Open files.    */
  279.  
  280.     if (!cmderror) {                /* Source file */
  281.     if ((In.Buf = (char *) malloc (BUFFSIZE)) == NULL)
  282.         quit_cleanup ("Out of memory!\n");
  283. #ifdef MSDOS
  284.     _iomode = 0x8000;
  285. #endif
  286.     if ((In.fd = open (SourceFN, 0)) < 0) {
  287.         fprintf (stderr, "Unable to open source file.\n");
  288.         In.fd = NULL;
  289.         cmderror = TRUE;
  290.     }
  291.     In.Ptr = In.Lim = In.Buf;
  292.     }
  293. #ifdef MSDOS
  294.     _iomode = 0;
  295. #endif
  296.     if (!cmderror && EquateFN[0])        /* Equate file */
  297.     cmderror |= xopen (EquateFN, &Eq, "equate");
  298.  
  299.     if (!cmderror && !SuppList)            /* Listing file */
  300.     cmderror |= xopen (ListFN, &List, "listing");
  301.  
  302. #ifdef MSDOS
  303.     if (!SFormat)
  304.     _iomode = 0x8000;
  305. #endif
  306.     if (!cmderror)                /* Object code file */
  307.     cmderror |= xopen (SrecFN, &Srec, "object code");
  308. #ifdef MSDOS
  309.     _iomode = 0x8000;
  310. #endif
  311.  
  312.     if (cmderror) {
  313.     fprintf (stderr, "\n");
  314.     fprintf (stderr, "Usage: a68k <source file>\n");
  315.     fprintf (stderr, "            [-d[[!]<prefix>]]\n");
  316.     fprintf (stderr, "            [-e[<equate file>]]\n");
  317.     fprintf (stderr, "            [-f]\n");
  318.     fprintf (stderr, "            [-h<header file>]\n");
  319.     fprintf (stderr, "            [-i<include dirlist>]\n");
  320.     fprintf (stderr, "            [-k]\n");
  321.     fprintf (stderr, "            [-l[<listing file>]]\n");
  322.     fprintf (stderr, "            [-n]\n");
  323.     fprintf (stderr, "            [-o<object file>]\n");
  324.     fprintf (stderr, "            [-p<page depth>]\n");
  325.     fprintf (stderr, "            [-q[<quiet interval>]]\n");
  326.     fprintf (stderr, "            [-s] [-t]\n");
  327.     fprintf (stderr, "            [-w[<hash size>][,<heap size>]]\n");
  328.     fprintf (stderr, "            [-x] [-y]\n");
  329.     fprintf (stderr, "            [-z[<debug start>][,<debug end>]]\n\n");
  330.     fprintf (stderr, "Heap size default:  -w");
  331.     fprintf (stderr, "%ld,%ld\n", (long) DEFHASH, (long) DEFHEAP2);
  332.     SrecFN[0] = '\0';    /* Don't scratch the object file! */
  333.     quit_cleanup ("\n");
  334.     }
  335.  
  336.     if (Quiet != 0) {
  337.     printf ("68000 Assembler - version %s\n", Version);
  338.     printf ("Copyright 1985 by Brian R. Anderson\n");
  339.     printf ("AmigaDOS conversion copyright 1989 by Charlie Gibbs.\n\n");
  340.     printf ("Assembling %s\n\n", SourceFN);
  341.     }
  342.  
  343. /* Allocate initial symbol table chunks. */
  344.  
  345.     templong = sizeof (struct SymTab *) * HashSize;
  346.     Hash = (struct SymTab **) malloc ((unsigned) templong);
  347.     if (Hash == NULL)
  348.     quit_cleanup ("Out of memory!\n");
  349.     for (hashptr = Hash, i = 0; i < HashSize; hashptr++, i++)
  350.     *hashptr = NULL;    /* Clear the hash table. */
  351.  
  352.     SymStart = (struct SymTab *) malloc ((unsigned) CHUNKSIZE);
  353.     if (SymStart == NULL)
  354.     quit_cleanup ("Out of memory!\n");
  355.     SymCurr = SymStart;            /* Make the first chunk current. */
  356.     SymCurr->Link = NULL;        /* Clear forward pointer. */
  357.     SymLim = SymCurr;
  358.     SymLim++;                /* Start of names */
  359.  
  360.     NameStart = (struct NameChunk *) malloc ((unsigned) CHUNKSIZE);
  361.     if (NameStart == NULL)
  362.     quit_cleanup ("Out of memory!\n");
  363.     NameCurr = NameStart;        /* Make the first chunk current. */
  364.     NameCurr->Link = NULL;        /* Clear forward pointer. */
  365.     NameLim = (char *) NameCurr + sizeof (char *);  /* Start of names */
  366.  
  367. /* Allocate the relocation attribute table. */
  368.  
  369.     RelStart = (struct RelTab *) malloc ((unsigned) CHUNKSIZE);
  370.     if (RelStart == NULL)
  371.     quit_cleanup ("Out of memory!\n");
  372.     RelCurr = RelStart;            /* Relocation table */
  373.     RelCurr->Link = NULL;        /* No additional chunks */
  374.     RelLast = NULL;            /* There are no entries yet. */
  375.     RelLim = RelStart;
  376.     RelLim++;                /* First unused space */
  377.  
  378. /* Allocate the secondary heap (input files and parser stack). */
  379.  
  380.     Heap2 = malloc ((unsigned) maxheap2);
  381.     if (Heap2 == NULL)
  382.     quit_cleanup ("Out of memory!\n");
  383.  
  384. /* Allocate the INCLUDE skip table. */
  385.  
  386.     SkipLim = (struct SkipEnt *) malloc ((unsigned) INCSKSIZ);
  387.     if (SkipLim == NULL)
  388.     quit_cleanup ("Out of memory!\n");
  389.     SkipIdx = SkipLim;
  390.     SetFixLim = (struct SetFixup *) ((char *) SkipLim + INCSKSIZ);
  391.     IncStart = 0;
  392.  
  393. /* Allocate the forward branch optimization log. */
  394.  
  395.     if (NoOpt) {
  396.     FwdStart = NULL;
  397.     } else {
  398.     FwdStart = (struct FwdTable *) malloc ((unsigned) FWDSIZE);
  399.     if (FwdStart == NULL)
  400.         quit_cleanup ("Out of memory!\n");
  401.     FwdCurr = FwdStart;    /* Make the first chunk current. */
  402.     FwdCurr->Link = NULL;    /* Clear forward pointer. */
  403.     FwdLim2 = (int *) ((char *) FwdCurr + sizeof (struct FwdTable *));
  404.     FwdPtr = FwdLim2;    /* Current position in pass 2 */
  405.     }
  406.  
  407. /*-------------------------------------------------------------------
  408.  
  409.     Begin Pass 1.
  410.                                    */
  411.     Pass2 = FALSE;
  412.     startpass ('1', maxheap2);
  413.     NumSyms = 0;    /* There's nothing in the symbol table yet. */
  414.     NextHunk = 0L;    /* Start in hunk zero. */
  415.     LowInF = InF;    /* Initialize secondary heap usage pointers. */
  416.     High2 = NextFNS;
  417.     Low2  = (char *) LowInF;
  418.     FwdLim1     = FwdBranch;    /* Forward branch controls */
  419.     FwdFixLimit = FwdBranchFix;
  420.  
  421.     /* Define ".A68K" as a SET symbol with an absolute value of 1.
  422.     This allows programs to identify this assembler.    */
  423.     AddSymTab (".A68K", 1L, (long) ABSHUNK, 0, 4);  /* All spellings */
  424.     AddSymTab (".A68k", 1L, (long) ABSHUNK, 0, 4);
  425.     AddSymTab (".a68K", 1L, (long) ABSHUNK, 0, 4);
  426.     AddSymTab (".a68k", 1L, (long) ABSHUNK, 0, 4);
  427.  
  428.     endfile = FALSE;
  429.     Dir = None;
  430.     while (!endfile && (Dir != End)) {
  431.     PrevDir = Dir;            /* Save previous directive. */
  432.     endfile = LineParts (dummy);    /* Get a statement. */
  433.     GetObjectCode (dummy);        /* Process the statement. */
  434.  
  435.     if (IncStart != 0) {
  436.         if ((OpCode[0] != '\0') && (Dir < SkipDir)) {
  437.         IncStart = 0;            /* We can't      */
  438.         if (SkipLim->Set1 != NULL) {    /*  skip this    */
  439.             SetFixLim = SkipLim->Set1;    /*  INCLUDE file */
  440.             SetFixLim++;        /*  in pass 2.   */
  441.         }
  442.         }
  443.     }
  444.     if ((HunkType == HunkNone) && (AddrAdv != 0)) {
  445.         DoSection ("", 0, "", 0, "", 0);    /* Start unnamed CODE section. */
  446.         MakeHunk = TRUE;
  447.     }
  448.     if ((Label[0] != '\0')            /* If the statement is labeled */
  449.     && (Dir != Set) && (Dir != Equr) && (Dir != Reg)) {
  450.         if (!ReadSymTab (Label)) {        /* Make a new entry. */
  451.         AddSymTab (Label, AddrCnt, CurrHunk, LineCount, 0);
  452.         } else if ((Sym->Flags & 1)        /* If dup., ignore... */
  453.         || (Sym->Defn == NODEF)) {        /* else fill in... */
  454.         Sym->Val = AddrCnt;        /* Current loc. */
  455.         Sym->Hunk = CurrHunk;        /* Hunk number */
  456.         Sym->Defn = LineCount;        /* Statement number */
  457.         Sym->Flags &= ~1;        /* Clear XREF flag. */
  458.         if (Sym->Flags & 0x80) {    /* If it's PUBLIC, */
  459.             Sym->Flags |= 2;        /*  make it XDEF. */
  460.         }
  461.         }
  462.         if (Dir == Equ) {
  463.         Sym->Val = ObjSrc;        /* Equated value */
  464.         Sym->Hunk = Src.Hunk;        /* Hunk number */
  465.         }
  466.         if (!NoOpt && (Dir != Equ)) {    /* Forward optimization */
  467.         PackFwdBranch (dummy);        /* Drop expired entries. */
  468.         fp1 = FwdBranch;
  469.         while (fp1 < FwdLim1) {        /* Scan forward branches. */
  470.             if (fp1->FwdSym == Sym) {    /* It branched here. */
  471.             if (fp1->Loc != (AddrCnt-4)) {    /* Don't make zero displacement! */
  472.                 if (fp1->Line < LineCount) {
  473.                 AddrCnt -= 2;    /* Shorten the program. */
  474.                 Sym->Val -= 2;    /* Move the label back. */
  475.                 for (fsp = FwdBranchFix; fsp < FwdFixLimit; fsp++) {
  476.                     if (fp1->Loc<(*fsp)->Val) {    /* Adjust labels  */
  477.                     (*fsp)->Val -= 2;    /*  within range. */
  478.                     }
  479.                 }
  480.                 }
  481.                 if ((char *) FwdLim2 >= ((char *) FwdCurr + FWDSIZE)) {
  482.                 FwdCurr->Link =    /* Get a new chunk. */
  483.                     (struct FwdTable *) malloc ((unsigned) FWDSIZE);
  484.                 if (FwdCurr->Link == NULL)
  485.                     quit_cleanup ("Out of memory!\n");
  486.                 FwdCurr = FwdCurr->Link;
  487.                 FwdLim2 = (int *)
  488.                     ((char *) FwdCurr + sizeof (struct FwdTable *));
  489.                 }
  490.                 *FwdLim2++ = fp1->Line; /* Flag this branch in pass 2. */
  491.             }
  492.             fp3 = fp2 = fp1;
  493.             fp3++;
  494.             while (fp3 < FwdLim1) {    /* Remove processed entry. */
  495.                 fp2->Loc    = fp3->Loc - 2;    /* Locations shifted too! */
  496.                 fp2->FwdSym = fp3->FwdSym;
  497.                 fp2->Line   = fp3->Line;
  498.                 fp2++;
  499.                 fp3++;
  500.             }
  501.             FwdLim1--;    /* Decrement table limit pointer. */
  502.             fp1--;        /* Offset increment below. */
  503.             }
  504.             fp1++;        /* Check the next entry. */
  505.         }
  506.         if (FwdLim1 > FwdBranch) {    /* Store labels within    */
  507.             *FwdFixLimit++ = Sym;    /*  range of fwd. branch. */
  508.         }
  509.         }
  510.     }
  511.     AddrCnt    += AddrAdv * DupFact;    /* Advance the location counter. */
  512.     }
  513.     if ((HunkType == HunkNone) && (NumSyms != 0)) { /* Dummy section   */
  514.     DoSection ("", 0, "", 0, "", 0);        /*  to get XDEF    */
  515.     MakeHunk = TRUE;                /*  symbols if any */
  516.     }
  517.     if (HunkType != HunkNone)
  518.     if (AddrCnt > OrgHigh)
  519.         Sect->Val = AddrCnt;    /* End of the last section */
  520.     else
  521.         Sect->Val = OrgHigh;    /* We've ORGed higher. */
  522.  
  523.     if (InclErrs)
  524.     quit_cleanup ("Fatal errors - assembly aborted\n");
  525.  
  526.     if (Quiet > 0)
  527.     fprintf (stderr, "%d\n", LineCount);
  528.     else if (Quiet < 0)
  529.     fprintf (stderr, "%d\n\n", InF->Line);
  530.  
  531.  
  532.  
  533. /*----------------------------------------------------------------
  534.  
  535.     Begin Pass 2.
  536.                                 */
  537.     Pass2 = TRUE;
  538.     lseek (In.fd, 0L, 0);        /* "Rewind" the source file. */
  539.     In.Ptr = In.Lim = In.Buf;
  540.     startpass ('2', maxheap2);
  541.     RefLim = (struct Ref *) SymLim;    /* Cross-reference table */
  542.  
  543. /* Calculate the total size of each section type,
  544.     reset all section pointers to the beginning, and
  545.     write all absolute symbols to an equate file if desired. */
  546.  
  547.     codesize = datasize = bsssize = 0;
  548.     if (EquateFN[0]) {
  549.     xputs (&Eq, "* Equate file for ");
  550.     xputs (&Eq, SourceFN);
  551.     xputs (&Eq, "\n* Created by");
  552.     xputs (&Eq, " A68k version ");
  553.     xputs (&Eq, Version);
  554.     xputs (&Eq, "\n");
  555.     }
  556.     Sym = SymChunk = SymStart;
  557.     Sym++;
  558.     SymChLim = (struct SymTab *) ((char *) SymChunk + CHUNKSIZE);
  559.     while (Sym) {
  560.     if (Sym->Flags & 0x10) {
  561.         templong = (Sym->Val + 3) & ~3L;        /* Hunk size */
  562.         j = (Sym->Hunk & 0x3FFF0000L) >> 16;    /* Hunk type */
  563.         if (j == HunkCode)        /* Accumulate sizes by type. */
  564.         codesize += templong;
  565.         else if (j == HunkData)
  566.         datasize += templong;
  567.         else
  568.         bsssize += templong;
  569.         Sym->Val = 0L;        /* Back to start of all sections */
  570.     }
  571.     if (EquateFN[0]) {
  572.         if (((Sym->Hunk & 0x00007FFFL) == ABSHUNK)
  573.         && ((Sym->Flags == 0) || (Sym->Flags == 2))) {
  574.         xputs (&Eq, Sym->Nam);
  575.         xputs (&Eq, "\tEQU\t$");
  576.         LongPut (&Eq, Sym->Val, 4);
  577.         xputs (&Eq, "\n");
  578.         }
  579.     }
  580.     Sym = NextSym (Sym);    /* Try for another symbol table entry. */
  581.     }
  582.     if (EquateFN[0])
  583.     xclose (&Eq);
  584.  
  585. /* Write sign-on messages for listing file. */
  586.  
  587.     LnCnt = LnMax;
  588.     PgCnt = 0;
  589.     if (!SuppList) {
  590.     CheckPage (&List, FALSE);        /* Print headings. */
  591.     xputs (&List, "68000 Assembler - version ");
  592.     xputs (&List, Version);
  593.     xputs (&List, "\nCopyright 1985 by Brian R. Anderson.\n");
  594.     xputs (&List, "AmigaDOS conversion copyright 1989");
  595.     xputs (&List, " by Charlie Gibbs.\n\n");
  596.     LnCnt += 4;
  597.     }
  598.  
  599.     StartSrec (&Srec, IdntName);    /* Write object header record. */
  600.  
  601. /*    Process the second pass.    */
  602.  
  603.     endfile = FALSE;
  604.     Dir = None;
  605.     while (!endfile && (Dir != End)) {
  606.     PrevDir = Dir;            /* Save previous directive. */
  607.     endfile = LineParts (dummy);    /* Get a statement. */
  608.     if (!endfile) {
  609.         GetObjectCode (dummy);    /* Process the statement. */
  610.         if (Label[0] != '\0') {    /* If statement is labeled, */
  611.         ReadSymTab (Label);    /*  check for duplicate defn. */
  612.         if (Sym->Defn != LineCount) {
  613.             AddRef (LineCount);    /* Got one - flag as reference. */
  614.             if (Dir == Set) {
  615.             if ((Sym->Flags & 4) == 0)
  616.                 Error (LabLoc, SymDup); /* Can't SET normal label. */
  617.             } else {
  618.             Error (LabLoc, SymDup);    /* Ordinary duplicate */
  619.             }
  620.         } else if (Dir == Set) {
  621.             AddRef (LineCount);    /* Flag all SETs as references. */
  622.         } else {
  623.             if (Sym->Val != AddrCnt)
  624.             if ((Dir != Equ) && (Dir != Equr) && (Dir != Reg))
  625.                 Error (0, Phase);    /* Assembler error */
  626.         }
  627.         }
  628.         WriteListLine (&List);
  629.         WriteSrecLine (&Srec);
  630.         AddrCnt += AddrAdv * DupFact;    /* Advance the location counter. */
  631.     } else {
  632.         Error (0, EndErr);        /* END statement is missing. */
  633.         WriteListLine (&List);
  634.     }
  635.     }
  636.     if ((HunkType == HunkNone) && (NumSyms != 0)) { /* Dummy section   */
  637.     DoSection ("", 0, "", 0, "", 0);        /*  to get XDEF    */
  638.     MakeHunk = TRUE;                /*  symbols if any */
  639.     }
  640.  
  641. /*----------------------------------------------------------------
  642.  
  643.     Clean up.
  644.                                 */
  645.  
  646.     if (HunkType != HunkNone)
  647.     if (AddrCnt > OrgHigh)
  648.         Sect->Val = AddrCnt;    /* End of the last section */
  649.     else
  650.         Sect->Val = OrgHigh;    /* We've ORGed higher. */
  651.  
  652.     if (Quiet > 0)
  653.     fprintf (stderr, "%d", LineCount);    /* Final line number */
  654.     else if (Quiet < 0)
  655.     fprintf (stderr, "%d\n", InF->Line);
  656.     fflush (stderr);            /* Make sure it gets out. */
  657.  
  658.     close (In.fd);        /* We're finished with the source file. */
  659.     In.fd = NULL;
  660.     free (In.Buf);
  661.     In.Buf = NULL;
  662.  
  663.     EndSdata (&Srec, EndAddr);    /* Write remaining data and end record. */
  664.     xclose (&Srec);        /* We're finished with the object file. */
  665.     if ((ErrorCount != 0) && (!keepobj))
  666.     unlink (SrecFN);    /* Scratch it if there were errors. */
  667.  
  668.     RelCurr = RelStart;
  669.     RelStart = NULL;
  670.     while (RelCurr != NULL) {
  671.     RelLim = RelCurr;
  672.     RelCurr = RelCurr->Link;
  673.     free (RelLim);        /* Free the relocation table. */
  674.     }
  675.  
  676.     if (Heap2 != NULL) {
  677.     free (Heap2);        /* Free the secondary heap. */
  678.     Heap2 = NULL;
  679.     }
  680.  
  681.     if (XrefList)
  682.     WriteSymTab (&List);    /* List the symbol table. */
  683.  
  684. /* Display final error count. */
  685.  
  686.     if (Quiet != 0)
  687.     fprintf (stderr, "\nEnd of assembly - ");
  688.     if (!SuppList)
  689.     xputs (&List, "\nEnd of assembly - ");
  690.     if (ErrorCount == 0) {
  691.     if (Quiet != 0)
  692.         fprintf (stderr, "no errors were found.\n");
  693.     if (!SuppList)
  694.         xputs (&List, "no errors were found.\n");
  695.     } else if (ErrorCount == 1) {
  696.     if (Quiet != 0)
  697.         fprintf (stderr, "1 error was found.\n");
  698.     if (!SuppList)
  699.         xputs (&List, "1 error was found.\n");
  700.     } else {
  701.     if (Quiet != 0)
  702.         fprintf (stderr, "%d errors were found.\n", ErrorCount);
  703.     if (!SuppList) {
  704.         sprintf (tempchar, "%d errors were found.\n", ErrorCount);
  705.         xputs (&List, tempchar);
  706.     }
  707.     }
  708.  
  709. /* Display heap usage. */
  710.  
  711.     if (Quiet != 0)
  712.     fprintf (stderr, "Heap usage:  -w%ld", HashSize);
  713.     if (!SuppList) {
  714.     sprintf (tempchar, "Heap usage:  -w%ld", HashSize);
  715.     xputs (&List, tempchar);
  716.     }
  717.     templong = (long) (High2 - Heap2);
  718.     if (Low2 < (char *) LowInF)
  719.     templong += (long) (Heap2 + maxheap2 - Low2);
  720.     else
  721.     templong += (long) (Heap2 + maxheap2 - (char *) LowInF);
  722.     if (Quiet != 0)
  723.     fprintf (stderr, ",%ld\n", templong);
  724.     if (!SuppList) {
  725.     sprintf (tempchar, ",%ld\n", templong);
  726.     xputs (&List, tempchar);
  727.     }
  728.  
  729. /* Display the total size of all section types. */
  730.  
  731.     if (Quiet != 0) {
  732.     fprintf (stderr, "Total hunk sizes:  %lx code, ", codesize);
  733.     fprintf (stderr, "%lx data, %lx BSS\n", datasize, bsssize);
  734.     }
  735.     if (!SuppList) {
  736.     sprintf (tempchar, "Total hunk sizes:  %lx code, ", codesize);
  737.     xputs (&List, tempchar);
  738.     sprintf (tempchar, "%lx data, %lx BSS\n", datasize, bsssize);
  739.     xputs (&List, tempchar);
  740.     }
  741.  
  742. /* Display hashing statistics if required. */
  743.  
  744.     if (HashStats && (NumSyms != 0)) {
  745.     printf ("\n");
  746.     printf ("HASH CHAIN STATISTICS - %d symbols\n\n", NumSyms);
  747.     templong = (NumSyms + 1) * sizeof (int);
  748.     HashCount = (int *) malloc ((unsigned) templong);
  749.     if (HashCount == NULL)
  750.         quit_cleanup ("Out of memory!\n");
  751.  
  752.     printf ("Length     No. of chains\n");
  753.     printf ("------     -------------\n");
  754.     intptr = HashCount;
  755.     for (i = 0; i <= NumSyms; i++)
  756.         *(intptr++) = 0;    /* Clear hash chain length counters. */
  757.  
  758.     hashptr = Hash;
  759.     for (i = 0; i < HashSize; i++) {
  760.         j = 0;
  761.         if ((Sym = *hashptr) != NULL) {
  762.         j++;        /* This chain has at least one entry. */
  763.         while ((Sym = Sym->Link) != NULL) {
  764.             j++;    /* Count entries in the chain. */
  765.         }
  766.         }
  767.         intptr = HashCount + j;
  768.         (*intptr)++;    /* Bump counter by chain length. */
  769.         hashptr++;
  770.     }
  771.     intptr = HashCount;
  772.     for (i = 0; i <= NumSyms; i++) {
  773.         if (*intptr)
  774.         printf ("%4d          %4d\n", i, *intptr);
  775.         intptr++;
  776.     }
  777.     free (HashCount);        /* Free hash statistics table. */
  778.     HashCount = NULL;
  779.     }
  780.  
  781. /* All done! */
  782.     if (!SuppList) {
  783.     xputs (&List, "\f");    /* One last page eject */
  784.     xclose (&List);        /* We're finished with the listing file. */
  785.     }
  786.     quit_cleanup ("");        /* Normal termination */
  787. }
  788.  
  789.  
  790.  
  791. /*======================================================================*/
  792. /*                                    */
  793. /*              Subroutines used by the main program            */
  794. /*                                    */
  795. /*======================================================================*/
  796.  
  797.  
  798.  
  799. int getfilename (name, arg, desc, needit)
  800. char *name, *arg, *desc;
  801. int needit;
  802. /* If "name" is not a duplicate, copies "arg" to it, else flags
  803.     duplicate using "desc".  If "needit" is TRUE, also flags
  804.     an error if "arg" is a null string.
  805.     Returns TRUE if an error is found, FALSE otherwise. */
  806. {
  807.     if (*name) {
  808.     fprintf (stderr, "%s file is declared more than once.\n", desc);
  809.     return (TRUE);
  810.     }
  811.     if (*arg) {
  812.     strcpy (name, arg);
  813.     return (FALSE);
  814.     }
  815.     if (needit) {
  816.     fprintf (stderr, "%s file name is missing\n", desc);
  817.     return (TRUE);
  818.     }
  819.     return (FALSE);
  820. }
  821.  
  822.  
  823.  
  824. int checkswitch (c, name) char c, *name;
  825. /* Displays an error message and returns TRUE if "c" isn't a NULL.
  826.     Just returns FALSE otherwise.                */
  827. {
  828.     if (c) {
  829.     fprintf (stderr, "Invalid %s switch.\n", name);
  830.     return (TRUE);
  831.     } else {
  832.     return (FALSE);
  833.     }
  834. }
  835.  
  836.  
  837.  
  838. defaultfile (name, ext) char *name, *ext;
  839. /* If "name" is a null string, search for the last period in "name"
  840.     (if any) and append "ext".
  841.     If "name" doesn't contain a period, append a period and "ext". */
  842. {
  843.     char *s;
  844.  
  845.     if (*name == '\0') {    /* If name isn't specified... */
  846.     strcpy (name,SourceFN);    /* Start with source file name. */
  847.     s = name+strlen(name);    /* Scan backwards for period. */
  848.     while (--s > name) {
  849.         if (*s == '.') {
  850.         *s = '\0';    /* Chop off name extension. */
  851.         break;
  852.         }
  853.     }
  854.     strcat (name, ext);    /* Add name extension. */
  855.     }
  856. }
  857.  
  858.  
  859.  
  860. int checkdupfile (name1, desc1, name2, desc2)
  861. char *name1, *desc1, *name2, *desc2;
  862. /* If "name1" is the same as "name2", display an error message using
  863.     "desc1" and "desc2" and return TRUE.  Otherwise, return FALSE. */
  864. {
  865.     if (strcmp (name1, name2) == 0) {
  866.     fprintf (stderr,
  867.         "%s and %s file names are the same.\n", desc1, desc2);
  868.     return (TRUE);
  869.     } else {
  870.     return (FALSE);
  871.     }
  872. }
  873.  
  874.  
  875.  
  876. startpass (pchar, maxheap2) char pchar; long maxheap2;
  877. /* Set up to start the next pass. */
  878. {
  879.     int dummy;
  880.  
  881.     if (Quiet > 0) {
  882.     fprintf (stderr, "PASS %c line ", pchar);
  883.     fflush (stderr);
  884.     } else if (Quiet < 0) {
  885.     fprintf (stderr, "PASS %c\n", pchar);
  886.     }
  887.     NextFNS = Heap2;
  888.     InF = (struct InFCtl *) (Heap2 + maxheap2);
  889.     InF--;
  890.     InFNum = OuterMac = SkipNest = InF->Pos = InF->MCnt = 0;
  891.     InF->Line = 0;
  892.     InF->UPtr = 0;
  893.     InF->NPtr = NextFNS;
  894.     InF->NArg = -1;
  895.     InF->MCnt = 0;
  896.     strcpy (NextFNS, SourceFN);
  897.     ShowFile (FALSE);            /* Show source file name. */
  898.     NextFNS += strlen (SourceFN) + 1;
  899.     LineCount = LabLine = MacCount = ErrorCount = 0;
  900.     AddrCnt = CurrHunk = SectStart = EndAddr = 0L;
  901.     HunkType = HunkNone;        /* We're not in a hunk yet. */
  902.     HunkFlags = SectLine = HunkSeq = 0;
  903.     ListOff = MakeHunk = InnrFMac = FALSE;
  904.     SmallData = -1;
  905.     TTLstring[0] = '\0';        /* Clear the title string. */
  906. }
  907.  
  908.  
  909.  
  910. quit_cleanup (s) char *s;
  911. /* Clean up and exit. */
  912. {
  913.     if (In.fd != NULL)            /* Close all files... */
  914.     close (In.fd);
  915.     if (In.Buf != NULL)            /*  and free buffers. */
  916.     free (In.Buf);
  917.     if (Srec.fd != NULL)
  918.     xclose (&Srec);
  919.     if (List.fd != NULL)
  920.     xclose (&List);
  921.     if (Eq.fd != NULL)
  922.     xclose (&Eq);
  923.  
  924.     if (Hash != NULL)
  925.     free (Hash);            /* Free the hash table. */
  926.  
  927.     SymCurr = SymStart;
  928.     while (SymCurr != NULL) {
  929.     SymLim = SymCurr;
  930.     SymCurr = SymCurr->Link;
  931.     free (SymLim);            /* Free the symbol table. */
  932.     }
  933.  
  934.     NameCurr = NameStart;
  935.     while (NameCurr != NULL) {
  936.     NameLim = (char *) NameCurr;
  937.     NameCurr = NameCurr->Link;
  938.     free (NameLim);            /* Free the name table. */
  939.     }
  940.  
  941.     RelCurr = RelStart;
  942.     while (RelCurr != NULL) {
  943.     RelLim = RelCurr;
  944.     RelCurr = RelCurr->Link;
  945.     free (RelLim);            /* Free the relocation table. */
  946.     }
  947.  
  948.     FwdCurr = FwdStart;
  949.     while (FwdCurr != NULL) {
  950.     FwdLim2 = (int *) FwdCurr;
  951.     FwdCurr = FwdCurr->Link;
  952.     free (FwdLim2);            /* Free the forward branch log. */
  953.     }
  954.  
  955.     if (Heap2 != NULL)
  956.     free (Heap2);            /* Free the secondary heap. */
  957.  
  958.     if (SymSort != NULL)
  959.     free (SymSort);            /* Free symbol table sort area. */
  960.  
  961.     if (HashCount != NULL)
  962.     free (HashCount);        /* Free hash statistics table. */
  963.  
  964.     if (*s) {                /* If we have an error message, */
  965.     if (SrecFN[0])
  966.         unlink (SrecFN);        /*  scratch the object file,    */
  967.     fprintf (stderr, "%s", s);    /*  display the error message,  */
  968.     exit (20);            /*  and die. */
  969.     } else {
  970.     exit (ErrorCount ? 10 : 0);    /* Normal termination */
  971.     }
  972. }
  973.